#ifndef __LIST_H_
#define __LIST_H_

#include <stdbool.h>
#include <stdio.h>

#define LIST_ERR_NONE 0
#define LIST_ERR_COMMON -1
#define LIST_ERR_NULL_LIST -2  // This error occurred, need list_create

typedef struct listNode {
    void *data;
    int size;
    struct listNode *next;
    struct listNode *prev;
} listNode;

typedef struct {
    struct listNode *head;
    int length;
} List;

/**
 * Create the list.
 * @param[i] The secondary pointer list.
 * 
 * @return NULL, create failed, otherwise, the list pointer.
 */ 
List *list_create(List **list);

/**
 * Destroy the list.
 * @param[i] The secondary pointer list.
 * 
 * @return 0 is success, otherwise failed.
 */
int list_destroy(List **list);

/**
 * Append data to the list.
 * @param[in] The data.
 * @param[in] The target list.
 * @param[in] The data size.
 * 
 * @return 0 is success, otherwise failed.
 */
int list_append(void *data, List *list, int size);

/**
 * Prepend data to the list.
 * @param[in] The data.
 * @param[in] The target list.
 * @param[in] The data size.
 * 
 * @return 0 is success, otherwise failed.
 */
int list_prepend(void *data, List *list, int size);

/**
 * Insert data to the list.
 * @param[in] The data.
 * @param[in] The index want insert.
 * @param[in] The target list.
 * @param[in] The data size.
 * 
 * @return 0 is success, otherwise failed.
 */
int list_insert(void *data, int i, List *list, int size);

/**
 * Replace data to the list.
 * @param[in] The data.
 * @param[in] The index want to replace.
 * @param[in] The target list.
 * @param[in] The data size.
 * 
 * @return 0 is success, otherwise failed.
 */
int list_replace(void *data, int i, List *list, int size);

/**
 * Remove specific index's data of the list.
 * @param[in] The index want to remove.
 * @param[in] The target list.
 * 
 * @return 0 is success, otherwise failed.
 */
int list_removeAt(int i, List *list);

/**
 * Remove all the data in the list.
 * @param[in] The target list.
 * 
 * @return 0 is success, otherwise failed.
 */
int list_removeAll(List *list);

/**
 * Check if the list have data.
 * @param[in] The target list.
 * 
 * @return true is empty, otherwise return false.
 */
bool isEmpty(List *list);

/**
 * Move index's data another index.
 * @param[in] The src index.
 * @param[in] The dest index.
 * @param[in] The target list.
 * 
 * @return 0 is success, otherwise failed.
 */
void list_move(int from, int to, List *list);

/**
 * Swap data of the list.
 * @param[in] The index 1.
 * @param[in] The index 2.
 * @param[in] The target list.
 * 
 * @return 0 is success, otherwise failed.
 */
void list_swap(int i, int j, List *list);

/**
 * Get the data count of the list.
 * @param[in] The target list.
 * 
 * @return The list data cout.
 */
int list_count(List *list);

/**
 * Read data from the list.
 * @param[in] The target list.
 * @param[in] The index.
 * 
 * @return NULL is failed, otherwise, the data pointer.
 */
void *list_data(List *list, int index);

/**
 * Read first data from the list.
 * @param[in] The target list.
 * @param[out] The data size.
 * 
 * @return NULL is failed, otherwise, the data pointer.
 */
void *list_get_first(List *list, int *size);

#endif
